#ifndef GAMEENGINE_GEOMETRY_BOX2D_H
#define GAMEENGINE_GEOMETRY_BOX2D_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Location/point2d.h>
#include <GameEngine/Geometry/Core/coords2d.h>
#include <GameEngine/Geometry/Lines/line2d.h>
#include <GameEngine/Geometry/CoordinateSystems/transformer2d.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

namespace Box2D {
	//! Point index along a 2D box
	enum Index {
		//! First point
		/*!
		 @note This is the bottom-left point of the box
		 */
		First = 0,
		//! Second point
		/*!
		 @note This is the top-left point of the box
		 */
		Second = 1,
		//! Third point
		/*!
		 @note This is the bottom-right point of the box
		 */
		Third = 2,
		//! Fourth point
		/*!
		 @note This is the top-right point of the box
		 */
		Fourth = 3
	};
}



//! Class used to represent an axis-aligned 2D box
/*!
 *  A 2D box whose axes are aligned on the X and Y axes. For non axis-aligned boxes, please
 *  use the Parallelogram2d class.
 *
 @note Most algorithms expect floating point operations. Type T should therefore
       not be an integer type
 */
template <class T>
class Box2d {

public:
	Box2d();
	Box2d(const T& x_min, const T& x_max, const T& y_min, const T& y_max);
	Box2d(const Point2d<T>& bottom_left, const Point2d<T>& top_right);
	Box2d(const Box2d& rhs);
	virtual ~Box2d();
	Box2d& operator=(const Box2d& rhs);

	Point2d<T> bottom_left() const;
	Point2d<T> bottom_right() const;
	Point2d<T> top_left() const;
	Point2d<T> top_right() const;

	T min_x() const;
	T max_x() const;
	T min_y() const;
	T max_y() const;

	Point2d<T> point(const Coords2d<T>& coords) const;
	Coords2d<T> coordinates(const Point2d<T>& pt) const;
	Transformer2d<T> transformer() const;
	Point2d<T> operator[](Box2D::Index index) const;

	bool inside(const Point2d<T>& rhs, bool strict = false) const;
	bool overlap(const Box2d& rhs) const;
	int intersection(const Line2d<T>& rhs, T& line_coordinate1, T& line_coordinate2, IntersectionType::Type* type = nil) const;
	bool closest_point(const Point2d<T>& rhs, Coords2d<T>& coords) const;
	Point2d<T> closest_point(const Point2d<T>& rhs) const;

	T perimeter() const;
	T area() const;

	bool degenerate(const T& tolerance = 0.000001) const;
	static bool in_box(const Coords2d<T>& coords, bool strict=false);

protected:
	//! Bottom-left point of the box
	Point2d<T> bottom_left_;

	//! Top-right point of the box
	Point2d<T> top_right_;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Surfaces/box2d.hpp>

#endif
